package pl.zuiol.games.poker.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * User: Damian
 * Date: 05.08.11
 * Time: 20:37
 */
public class HandValue implements Comparable<HandValue>{

    public enum Category{
        HIGH_CARD{
            public int compareCategory(List<Card> hand1, List<Card> hand2){

                System.out.println("HighCard comparation");
                Collections.sort(hand1);
                Collections.sort(hand2);
                System.out.println(hand1.get(4).getRank().toString());
                int result = 0;
                for(int i = 4; i >=0; i--){
                    result = hand1.get(i).getRank().compareTo(hand2.get(i).getRank());
                    if(result != 0)
                        break;
                }
                return result;
            }
        },
        PAIR{
            @Override
            public int compareCategory(List<Card> hand1, List<Card> hand2){

                System.out.println("Pair comparation");
                Collections.sort(hand1);
                Collections.sort(hand2);

                Rank firstPairRank = null;
                Rank secondPairRank = null;
                int i, k;
                for(i = 4; i > 0; i--){
                    if(hand1.get(i).getRank().compareTo(hand1.get(i - 1 ).getRank()) == 0){
                        firstPairRank = hand1.get(i).getRank();
                        break;
                    }
                }

                for(k = 4; k > 0; k--){
                    if(hand2.get(k).getRank().compareTo(hand2.get(k - 1).getRank()) == 0){
                        secondPairRank = hand2.get(k).getRank();
                        break;
                    }
                }

                if(firstPairRank.compareTo(secondPairRank) != 0)
                    return  firstPairRank.compareTo(secondPairRank);

                hand1.remove(i -1);
                hand1.remove(i -1);
                hand2.remove(k -1);
                hand2.remove(k -1);

                for(int z = 2; z >= 0; z--){
                    if(hand1.get(z).compareTo(hand2.get(z)) != 0 )
                        return hand1.get(z).compareTo(hand2.get(z));

                }
                return 0;

            }
        },
        TWO_PAIRS{
            @Override
            int compareCategory(List<Card> hand1, List<Card> hand2) {
                System.out.println("Two Pair comparation");
                Collections.sort(hand1);
                Collections.sort(hand2);

                Rank firstPairRank1 = null;
                Rank secondPairRank1 = null;
                Rank firstPairRank2 = null;
                Rank secondPairRank2 = null;

                int i, k;
                for(i = 4; i > 0; i--){
                    if(hand1.get(i).getRank().compareTo(hand1.get(i - 1).getRank()) == 0){
                        firstPairRank1 = hand1.get(i).getRank();
                        break;
                    }
                }

                 for(k = 4; k > 0; k--){
                    if(hand2.get(k).getRank().compareTo(hand2.get(k - 1).getRank()) == 0){
                        firstPairRank2 = hand2.get(k).getRank();
                        break;
                    }
                }

                if(firstPairRank1.compareTo(firstPairRank2) != 0){
                   return firstPairRank1.compareTo(firstPairRank2);
                }

                hand1.remove(i - 1);
                hand1.remove(i - 1);
                hand2.remove(k - 1);
                hand2.remove(k - 1);

                for(i = 2; i > 0; i--){
                    if(hand1.get(i).getRank().compareTo(hand1.get(i - 1).getRank()) == 0){
                        secondPairRank1 = hand1.get(i).getRank();
                        break;
                    }
                }

                 for(k = 2; k > 0; k--){
                    if(hand2.get(k).getRank().compareTo(hand2.get(k - 1).getRank()) == 0){
                        secondPairRank2 = hand2.get(k).getRank();
                        break;
                    }
                }

                if(secondPairRank1.compareTo(secondPairRank2) != 0){
                   return secondPairRank1.compareTo(secondPairRank2);
                }

                hand1.remove(i - 1);
                hand1.remove(i - 1);
                hand2.remove(k - 1);
                hand2.remove(k - 1);

                return hand1.get(0).compareTo(hand2.get(0));
            }
        },
        THREE_OF_KIND{
            @Override
            int compareCategory(List<Card> hand1, List<Card> hand2) {

                System.out.println("Three of Kind comparation");

                Collections.sort(hand1);
                Collections.sort(hand2);

                Rank firstThreeRank = null;
                Rank secondThreeRank = null;

                int i, k;
                for(i = 4; i > 0; i--){
                    if(hand1.get(i).getRank().compareTo(hand1.get(i - 1).getRank()) == 0){
                        firstThreeRank = hand1.get(i).getRank();
                        break;
                    }
                }

                for(k = 4; k > 0; k--){
                    if(hand2.get(k).getRank().compareTo(hand2.get(k - 1).getRank()) == 0){
                        secondThreeRank = hand2.get(k).getRank();
                        break;
                    }
                }

                if(firstThreeRank.compareTo(secondThreeRank) != 0){
                    return firstThreeRank.compareTo(secondThreeRank);
                }

                hand1.remove(i - 2);
                hand1.remove(i - 2);
                hand1.remove(i - 2);
                hand2.remove(k - 2);
                hand2.remove(k - 2);
                hand2.remove(k - 2);

                for(int z = 1; z >= 0; z--){
                    if(hand1.get(z).compareTo(hand2.get(z)) != 0 )
                        return hand1.get(z).compareTo(hand2.get(z));
                }

                return 0;  //To change body of implemented methods use File | Settings | File Templates.
            }
        },
        STRAIGHT{
            @Override
            int compareCategory(List<Card> hand1, List<Card> hand2) {

                System.out.println("straight comparation");
                Collections.sort(hand1);
                Collections.sort(hand2);

                System.out.println(hand1.get(4).getRank().toString());
                int result = 0;
                for(int i = 4; i >=0; i-- ){
                    result = hand1.get(i).getRank().compareTo(hand2.get(i).getRank());
                    if(result != 0)
                        break;
                }
                return result;
            }
        },
        FLUSH{
            @Override
            int compareCategory(List<Card> hand1, List<Card> hand2) {
                 System.out.println("flush comparation");
                Collections.sort(hand1);
                Collections.sort(hand2);

                System.out.println(hand1.get(4).getRank().toString());
                int result = 0;
                for(int i = 4; i >=0; i-- ){
                    result = hand1.get(i).getRank().compareTo(hand2.get(i).getRank());
                    if(result != 0)
                        break;
                }
                return result;
            }
        },
        FULL_HOUSE{
            @Override
            int compareCategory(List<Card> hand1, List<Card> hand2) {
                System.out.println("fullHouse comparation");
                Collections.sort(hand1);
                Collections.sort(hand2);

                Rank strongCardFirst = null;
                Rank strongCardSecond = null;
                Rank lowCardFirst = null;
                Rank lowCardSecond = null;

                if(hand1.get(0).getRank().compareTo(hand1.get(2).getRank()) == 0){
                    strongCardFirst = hand1.get(0).getRank();
                    lowCardFirst = hand1.get(4).getRank();
                }
                else{
                    strongCardFirst = hand1.get(4).getRank();
                    lowCardFirst = hand1.get(0).getRank();
                }

                if(hand2.get(0).getRank().compareTo(hand2.get(2).getRank()) == 0){
                    strongCardSecond = hand2.get(0).getRank();
                    lowCardSecond = hand2.get(4).getRank();
                }
                else{
                    strongCardSecond = hand2.get(4).getRank();
                    lowCardSecond = hand2.get(0).getRank();
                }

                if(strongCardFirst.compareTo(strongCardSecond) != 0){
                    return  strongCardFirst.compareTo(strongCardSecond);
                }

                return lowCardFirst.compareTo(lowCardSecond);

            }
        },
        FOUR_OF_KIND{
            @Override
            int compareCategory(List<Card> hand1, List<Card> hand2) {
                System.out.println("four of kind comparation");

                Collections.sort(hand1);
                Collections.sort(hand2);

                Rank fourFirst = null;
                Rank fourSecond = null;

                if(hand1.get(0).getRank().compareTo(hand1.get(1).getRank()) == 0){
                    fourFirst = hand1.get(0).getRank();
                }
                else{
                    fourFirst = hand1.get(4).getRank();
                }

                if(hand2.get(0).getRank().compareTo(hand2.get(1).getRank()) == 0){
                    fourSecond = hand2.get(0).getRank();
                }
                else{
                    fourSecond = hand2.get(4).getRank();
                }

                return fourFirst.compareTo(fourSecond);
            }
        },
        STRAIGHT_FLUSH{
            @Override
            int compareCategory(List<Card> hand1, List<Card> hand2) {

                System.out.println("straightFlush comparation");
                Collections.sort(hand1);
                Collections.sort(hand2);

                System.out.println(hand1.get(4).getRank().toString());
                int result = 0;
                for(int i = 4; i >=0; i-- ){
                    result = hand1.get(i).getRank().compareTo(hand2.get(i).getRank());
                    if(result != 0)
                        break;
                }
                return result;
            }
        };

        abstract int compareCategory(List<Card> hand1, List<Card> hand2);
    }

    private Category mHandValue;
    private List<Card> fiveCards;

    private HandValue(){}

    public HandValue(Category category, Card[] hand){
        fiveCards = new ArrayList<Card>();
        for(Card card : hand){
            fiveCards.add(card);
        }
        mHandValue = category;
    }

    public HandValue(Category category, List<Card> hand){
        fiveCards = hand;

    }

    public Category getCategory(){
        return this.mHandValue;
    }

    public List<Card> getFiveCards(){
        return fiveCards;
    }

    public int compareTo(HandValue o) {

        System.out.println("Comparation");
        int categoryResult = mHandValue.ordinal() - o.getCategory().ordinal();
        return (categoryResult != 0) ? categoryResult : mHandValue.compareCategory(fiveCards, o.getFiveCards());
    }

}
